﻿#region COPYRIGHT
//--------------------------------------------------------------------------------
// <copyright file="GeometryBuffer.cs" company="starLiGHT Entertainment Studios">
//    Copyright (c) 2011 
//       Roland Rosenkranz (Glatzemann@email.de)
// </copyright>
// <license>
//   This file is part of starLiGHT.GUI.
//
//   It is released under the Microsoft Public License (Ms-PL).
//
//   You should have received a copy of the Microsoft Public License
//   along with starLiGHT.GUI. If not, see http://sle.codeplex.com/license.
//    
//   ADDITIONAL (commercial) LICENSES for starLiGHT.GUI are available on request.
// </license>
// <version>
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev::                       $:  Revision of last commit *
// * $Author::                    $:  Author of last commit   *
// * $Date::                      $:  Date of last commit     *
// ************************************************************
// </version>
//--------------------------------------------------------------------------------
#endregion

#if !XNA4

namespace starLiGHT.GUI
{
#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using starLiGHT.Collections;
#endregion

    public class GeometryBuffer : IDisposable
    {
        private GraphicsDevice graphics;
        private Vector2 location;
        private bool translationDirty;
        private Matrix translation;
        private VertexDeclaration vertexDeclaration;
        private VertexBuffer vertexBuffer;
        private FastList<VertexPositionColorTexture> localBuffer;
        private int primitiveCount;
        private bool filling;

        public GeometryBuffer(GraphicsDevice graphics)
        {
            this.graphics = graphics;
            this.translationDirty = true;
            this.translation = Matrix.Identity;
            this.vertexDeclaration = new VertexDeclaration(graphics, VertexPositionColorTexture.VertexElements);
            this.vertexBuffer = new VertexBuffer(graphics, typeof(VertexPositionColorTexture), 1000, BufferUsage.None);
            this.localBuffer = new FastList<VertexPositionColorTexture>();
        }

        ~GeometryBuffer()
        {
            this.Dispose();
        }

        public Vector2 Location
        {
            get
            {
                return this.location;
            }

            set
            {
                if (this.location != value)
                {
                    this.location = value;
                    this.translationDirty = true;
                }
            }
        }

        public Matrix Translation
        {
            get
            {
                if (this.translationDirty)
                {
                    this.translation = Matrix.CreateTranslation(this.location.X, this.location.Y, 0.0f);
                    this.translationDirty = false;
                }

                return this.translation;
            }
        }

        public VertexDeclaration VertexDeclaration
        {
            get
            {
                return this.vertexDeclaration;
            }
        }

        public VertexBuffer VertexBuffer
        {
            get
            {
                return this.vertexBuffer;
            }
        }

        public void Begin()
        {
            this.primitiveCount = 0;
            this.filling = true;
        }

        public void End()
        {
            if (this.localBuffer.Count > 0)
            {
                this.vertexBuffer.SetData<VertexPositionColorTexture>(this.localBuffer.ToArray());
                this.localBuffer.Clear();
            }

            this.filling = false;
        }

        public void AddTexturedQuad(float depth, float x, float y, float width, float height, float texX, float texY, float texWidth, float texHeight)
        {
            float left = x;
            float right = left + width;
            float top = y;
            float bottom = top + height;

            float texLeft = texX;
            float texRight = texX + texWidth;
            float texTop = texY;
            float texBottom = texY + texHeight;

            this.localBuffer.Add(new VertexPositionColorTexture(new Vector3(right, top, depth), Color.White, new Vector2(texRight, texTop)));
            this.localBuffer.Add(new VertexPositionColorTexture(new Vector3(left, bottom, depth), Color.White, new Vector2(texLeft, texBottom)));
            this.localBuffer.Add(new VertexPositionColorTexture(new Vector3(left, top, depth), Color.White, new Vector2(texLeft, texTop)));
            this.localBuffer.Add(new VertexPositionColorTexture(new Vector3(left, bottom, depth), Color.White, new Vector2(texLeft, texBottom)));
            this.localBuffer.Add(new VertexPositionColorTexture(new Vector3(right, top, depth), Color.White, new Vector2(texRight, texTop)));
            this.localBuffer.Add(new VertexPositionColorTexture(new Vector3(right, bottom, depth), Color.White, new Vector2(texRight, texBottom)));

            this.primitiveCount += 2;
        }

        public void AddTiledRectangle(float depth, float[] x, float[] y, float[] tx, float[] ty)
        {
            this.AddTexturedQuad(depth, x[0], y[0], x[1] - x[0], y[1] - y[0], tx[0], ty[0], tx[1] - tx[0], ty[1] - ty[0]);
            this.AddTexturedQuad(depth, x[1], y[0], x[2] - x[1], y[1] - y[0], tx[1], ty[0], tx[2] - tx[1], ty[1] - ty[0]);
            this.AddTexturedQuad(depth, x[2], y[0], x[3] - x[2], y[1] - y[0], tx[2], ty[0], tx[3] - tx[2], ty[1] - ty[0]);

            this.AddTexturedQuad(depth, x[0], y[1], x[1] - x[0], y[2] - y[1], tx[0], ty[1], tx[1] - tx[0], ty[2] - ty[1]);
            this.AddTexturedQuad(depth, x[1], y[1], x[2] - x[1], y[2] - y[1], tx[1], ty[1], tx[2] - tx[1], ty[2] - ty[1]);
            this.AddTexturedQuad(depth, x[2], y[1], x[3] - x[2], y[2] - y[1], tx[2], ty[1], tx[3] - tx[2], ty[2] - ty[1]);

            this.AddTexturedQuad(depth, x[0], y[2], x[1] - x[0], y[3] - y[2], tx[0], ty[2], tx[1] - tx[0], ty[3] - ty[2]);
            this.AddTexturedQuad(depth, x[1], y[2], x[2] - x[1], y[3] - y[2], tx[1], ty[2], tx[2] - tx[1], ty[3] - ty[2]);
            this.AddTexturedQuad(depth, x[2], y[2], x[3] - x[2], y[3] - y[2], tx[2], ty[2], tx[3] - tx[2], ty[3] - ty[2]);
        }

        public void Dispose()
        {
            if (this.vertexBuffer != null)
            {
                this.vertexBuffer.Dispose();
                this.vertexBuffer = null;
            }

            if (this.localBuffer != null)
            {
                this.localBuffer = null;
            }
        }

        public void Draw()
        {
            if (this.filling)
            {
                throw new Exception("you have to call End() before drawing");
            }

            if (this.primitiveCount > 0)
            {
                this.graphics.VertexDeclaration = this.vertexDeclaration;
                this.graphics.Vertices[0].SetSource(this.vertexBuffer, 0, VertexPositionColorTexture.SizeInBytes);
                this.graphics.DrawPrimitives(PrimitiveType.TriangleList, 0, this.primitiveCount);
            }
        }
    }
}
#endif